<template>
    <div class="container">
      <el-row>
        <el-col :span="6">
          <div class="tree-container">
            <el-input
              placeholder="输入关键字进行过滤"
              v-model="filterText"
              clearable
            />
            <div v-if="treeLoading" class="loading-status">
              <i class="el-icon-loading" /> 加载设备树中...
            </div>
            <el-tree
              v-else
              class="filter-tree"
              :data="empData"
              :props="defaultProps"
              :filter-node-method="filterNode"
              @node-click="handler"
              ref="tree"
            />
          </div>
        </el-col>
        <el-col :span="18">
          <div v-if="params.device_id" class="chart-wrapper">
            <div v-if="chartLoading" class="loading-status">
              <i class="el-icon-loading" /> 数据加载中...
            </div>
            <template v-else>
              <div class="legend-container">
                <div
                  v-for="field in fields"
                  :key="field.value"
                  class="legend-item"
                  :class="{ active: selectedField === field.value }"
                  @click="switchChart(field.value)"
                >
                  <span 
                    class="color-indicator"
                    :style="{ backgroundColor: field.color }"
                  />
                  <span class="legend-label">{{ field.label }}</span>
                </div>
              </div>
              <div 
                ref="chartDom" 
                class="chart-content"
                v-show="chartDomReady"
                :data-loading="!chartDomReady"
              ></div>
            </template>
          </div>
          <div v-else class="empty-tip">
             请从左侧选择监测设备
          </div>
        </el-col>
      </el-row>
    </div>
  </template>
  <script>
  import { Area } from '@antv/g2plot'
  import { get } from '@/utils/request'
  import { debounce } from 'lodash'
  import moment from 'moment'
  
  export default {
    data() {
      return {
        filterText: '',
        empData: [],
        defaultProps: {
          children: 'children',
          label: 'name'
        },
        params: {
          device_id: null,
          engineer_id: null,
          page: 1,
          pageSize:150,
        },
        rawData: [],
        fields: [
          { label: '温度', value: 'temperature', color: '#1890ff' },
          { label: '湿度', value: 'humidity', color: '#2fc25b' },
          { label: 'TSP', value: 'tsp', color: '#facc14' },
          { label: 'PM10', value: 'pm10', color: '#f04864' },
          { label: 'PM2.5', value: 'pm25', color: '#8543e0' }
        ],
        selectedField: 'temperature',
        chartInstance: null,
        resizeObserver: null,
        treeLoading: true,
        chartLoading: false,
        chartDomReady: false,
        renderRetryCount: 0
      }
    },
  
    computed: {
      currentColor() {
        return this.fields.find(f => f.value === this.selectedField)?.color || '#1890ff'
      }
    },
  
    watch: {
      filterText(val) {
        this.$refs.tree?.filter(val)
      }
    },
  
    async mounted() {
      try {
        await this.getEmpData()
      } catch (error) {
        console.error('初始化失败:', error)
        this.$message.error('系统初始化失败，请刷新页面')
      }
    },
  
    beforeDestroy() {
      this.chartDomReady = false
      this.resizeObserver?.disconnect()
      if (this.chartInstance) {
        this.chartInstance.destroy()
        this.chartInstance = null
      }
    },
    methods: {
      filterNode(value, data) {
        if (!value) return true
        return data.name.toLowerCase().includes(value.toLowerCase())
      },
  
      handler(node) {
        if (!node.children) {
          this.params.device_id = node.id
          this.params.engineer_id = node.engineer_id
          this.fetchChartData()
        }
      },
  
      async getEmpData() {
        this.treeLoading = true
        try {
          const res = await get('/dashboard/findEngineerDeviceTree')
          if (res?.data?.code === 200) {
            this.empData = res.data.data || []
          } else if (Array.isArray(res?.data)) {
            this.empData = res.data
          } else {
            throw new Error('设备树格式错误')
          }
        } catch (error) {
          console.error('获取设备树失败:', error)
          this.$message.error('设备加载失败: ' + error.message)
        } finally {
          this.treeLoading = false
        }
      },
  
      async fetchChartData() {
        this.chartLoading = true
        this.chartDomReady = false
        try {
          const res = await get('/monitor/pageQueryTodayData', this.params)
          
          if (res.data?.list) {
            this.rawData = res.data.list.map(item => ({
              insert_time: this.parseTimestamp(item.insert_time),
              tsp: this.safeParseNumber(item.tsp),
              pm10: this.safeParseNumber(item.pm10),
              pm25: this.safeParseNumber(item.pm25),
              temperature: this.safeParseNumber(item.temperature),
              humidity: this.safeParseNumber(item.humidity)
            }))
  
            // 等待DOM更新
            await this.$nextTick()
            this.chartDomReady = true
            await this.$nextTick()
            this.renderChart()
          }
        } catch (error) {
          console.error('数据处理失败:', error)
          this.$message.error(error.message)
          this.rawData = []
        } finally {
          this.chartLoading = false
        }
      },
  
      parseTimestamp(ts) {
        try {
          const timestamp = typeof ts === 'string' ? parseInt(ts) : ts
          return moment(timestamp).format('HH:mm')
        } catch {
          return '--'
        }
      },
      safeParseNumber(value) {
        if (value === undefined || value === null) return 0
        if (typeof value === 'string' && value.trim() === '') return 0
        const num = Number(value)
        return isNaN(num) ? 0 : num
      },
  
      renderChart() {
        const MAX_RETRY = 3
        const container = this.$refs.chartDom
        
        // 容器检查
        if (!container || !container.offsetParent) {
          if (this.renderRetryCount < MAX_RETRY) {
            this.renderRetryCount++
            console.warn(`图表容器未就绪，第${this.renderRetryCount}次重试...`)
            setTimeout(() => this.renderChart(), 500)
            return
          }
          this.$message.error('图表初始化失败：无法找到容器元素')
          return
        }
        this.renderRetryCount = 0
  
        // 清理旧实例
        if (this.chartInstance) {
          this.chartInstance.destroy()
          this.chartInstance = null
        }
  
        try {
          // 数据验证
          const requiredFields = ['insert_time', this.selectedField]
          if (!this.rawData.every(item => 
            requiredFields.every(field => field in item)
          )) {
            throw new Error(`缺少必要字段：${requiredFields.join(', ')}`)
          }
  
          // 创建图表
          this.chartInstance = new Area(container, {
            data: this.processChartData(),
            xField: 'insert_time',
            yField: this.selectedField,
            xAxis: {
              //type:'insret_time',
             //tickCount: 55,
              label: {
                style: {
                  fontSize: 12,
                  fill: '#666'
                }
              }
            },
            yAxis: {
              label: {
                style: {
                  fontSize: 12,
                  fill: '#666'
                }
              }
            },
            areaStyle: () => ({
              fill: `l(270) 0:#ffffff 0.5:${this.currentColor} 1:${this.currentColor}`
            }),
            line: {
              color: this.currentColor,
              size: 2
            },
            smooth: true,
            animations: true,
            padding: [20, 50, 50, 50]
          })
          
          this.chartInstance.render()
          this.initResizeObserver()
        } catch (error) {
          console.error('图表初始化失败:', error)
          this.$message.error(`图表错误: ${error.message}`)
        }
      },
  
      processChartData() {
        return this.rawData
          .filter((_, i) => i % 1 === 0)
          .map(item => ({
            ...item,
            [this.selectedField]: this.safeParseNumber(item[this.selectedField])
          }))
      },
      initResizeObserver() {
        if (!this.$refs.chartDom) return
        
        if (this.resizeObserver) {
          this.resizeObserver.disconnect()
        }
  
        this.resizeObserver = new ResizeObserver(
          debounce(() => {
            try {
              this.chartInstance?.render()
            } catch (error) {
              console.error('图表重渲染失败:', error)
            }
          }, 300)
        )
        this.resizeObserver.observe(this.$refs.chartDom)
      },
  
      switchChart(field) {
        if (this.selectedField !== field) {
          this.selectedField = field
          this.renderChart()
        }
      }
    }
  }
  </script>
  
  <style lang="scss" scoped>
  /* 新增样式 */
  .chart-content {
    position: relative;
    transition: opacity 0.3s ease;
  
    &::before {
      content: '图表加载中...';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      color: #909399;
      display: none;
    }
  
    &[data-loading="true"]::before {
      display: block;
    }
  }
  
  /* 保持原有样式不变 */
  .container {
    height: 100vh;
    background: #f5f7fa;
  
    .el-row {
      height: 100%;
      
      .el-col {
        height: 100%;
      }
    }
  
    .tree-container {
      height: 100%;
      background: #fff;
      border-right: 1px solid #ebeef5;
      padding: 10px;
      display: flex;
      flex-direction: column;
  
      .loading-status {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #909399;
        font-size: 14px;
      }
  
      .filter-tree {
        flex: 1;
        overflow: auto;
        margin-top: 10px;
      }
    }
  
    .chart-wrapper {
      height: 100%;
      padding: 20px;
      background: #fff;
  
      .loading-status {
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #909399;
      }
  
      .legend-container {
        display: flex;
        flex-wrap: wrap;
        gap: 15px;
        margin-bottom: 20px;
  
        .legend-item {
          display: flex;
          align-items: center;
          padding: 8px 15px;
          border-radius: 4px;
          cursor: pointer;
          transition: all 0.3s;
          background: #f8f9fa;
          border: 1px solid #ebeef5;
          user-select: none;
  
          &.active {
            border-color: #409eff;
            background-color: rgba(64, 158, 255, 0.1);
          }
  
          .color-indicator {
            width: 12px;
            height: 12px;
            border-radius: 2px;
            margin-right: 8px;
          }
  
          .legend-label {
            font-size: 14px;
            color: #606266;
          }
        }
      }
  
      .chart-content {
        width: 120vh;
        height: 70vh;
        min-height: 400px;
      }
    }
  
    .empty-tip {
      height: 100%;
      display: flex;
      //align-items: center;
      justify-content: center;
      color:red;
      font-size: 16px;
      background-color:#ffffff;
    }
  }
  </style>